home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / VOL_400 / 429_01 / CHESS12 / CHESSUI.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-29  |  13.8 KB  |  604 lines

  1. #include "misc.hpp"
  2. #include "brdsize.hpp"
  3. #include "chess.hpp"
  4. #include "chessui.hpp"
  5. #include "chcharui.hpp"
  6.  
  7. CHESSUSERIFACE ChessUI;
  8.  
  9. const char whiteText[] = "White",
  10.            blackText[] = "Black";
  11.  
  12. LOCAL const char *colorText(PIECECOLOR color)
  13.   { return(color == WHITE ? whiteText : blackText); }
  14.  
  15. // returns piece abbreviation to be displayed in board squares
  16. // for a given piece
  17. LOCAL const char *pieceAbbrev
  18.   (
  19.     PIECECOLOR color,
  20.     PIECETYPE type
  21.   )
  22.   {
  23.     if (color == WHITE)
  24.       switch (type)
  25.         {
  26.     case TYPEKING:   return("WK");
  27.     case TYPEQUEEN:  return("WQ");
  28.     case TYPEBISHOP: return("WB");
  29.     case TYPEKNIGHT: return("WN");
  30.     case TYPEROOK:   return("WR");
  31.     case TYPEPAWN:   return("WP");
  32.     }
  33.     else
  34.       switch (type)
  35.         {
  36.     case TYPEKING:   return("BK");
  37.     case TYPEQUEEN:  return("BQ");
  38.     case TYPEBISHOP: return("BB");
  39.     case TYPEKNIGHT: return("BN");
  40.     case TYPEROOK:   return("BR");
  41.     case TYPEPAWN:   return("BP");
  42.     }
  43.     return(""); // dummy return
  44.   }
  45.  
  46. const char kingText[] = " King",
  47.            queenText[] = " Queen",
  48.            bishopText[] = " Bishop",
  49.            knightText[] = " Knight",
  50.            rookText[] = " Rook",
  51.            pawnText[] = " Pawn";
  52.  
  53. // fills in two entries in a message textList with color/name of
  54. // a piece
  55. LOCAL void pieceText
  56.   (
  57.     PIECECOLOR color,
  58.     PIECETYPE type,
  59.     const char **textList
  60.   )
  61.   {
  62.     *(textList++) = colorText(color);
  63.  
  64.     switch (type)
  65.       {
  66.       case TYPEKING:
  67.     *textList = kingText;
  68.     return;
  69.  
  70.       case TYPEQUEEN:
  71.     *textList = queenText;
  72.     return;
  73.  
  74.       case TYPEBISHOP:
  75.     *textList = bishopText;
  76.     return;
  77.  
  78.       case TYPEKNIGHT:
  79.     *textList = knightText;
  80.     return;
  81.  
  82.       case TYPEROOK:
  83.     *textList = rookText;
  84.     return;
  85.  
  86.       case TYPEPAWN:
  87.     *textList = pawnText;
  88.     return;
  89.       }
  90.   }
  91.  
  92. // base textLists for messages.  terminated by null pointers.  some
  93. // have null pointer place holders for variable portions of message.
  94.  
  95. const char *noMemory[] =
  96.   {
  97.     "Insufficient memory.  Press any key to exit:",
  98.     (char *) 0
  99.   };
  100.  
  101. const char *checkMated[] =
  102.   {
  103.     (char *) 0,
  104.     " King in checkmate.  Press any key to exit:",
  105.     (char *) 0
  106.   };
  107. const int MATEDCOLORINDEX = 0;
  108.  
  109. const char *staleMate[] =
  110.   {
  111.     (char *) 0,
  112.     " King in stalemate.  Press any key to exit:",
  113.     (char *) 0
  114.   };
  115. const int STALEMATEDCOLORINDEX = 0;
  116.  
  117. const char *selectPiece[] =
  118.   {
  119.     (char *) 0,
  120.     " Player:  Select piece to move with arrow keys, then hit enter:",
  121.     (char *) 0
  122.   };
  123. const int SELECTCOLORINDEX = 0;
  124.  
  125. const char *illegalSelection[] =
  126.   {
  127.     "That location does not contain one of your pieces."
  128.     "  Press any key to try again:",
  129.     (char *) 0
  130.   };
  131.  
  132. const char *moveIllegal[] =
  133.   {
  134.     "You cannot move the selected piece to that location."
  135.     "  Press any key to try again:",
  136.     (char *) 0
  137.   };
  138.  
  139. const char *wouldLoseKing[] =
  140.   {
  141.     "This move would result in your King being taken by the ",
  142.     (char *) 0,
  143.     (char *) 0,
  144.     ".  Press any key to select another move:",
  145.     (char *) 0
  146.   };
  147. const int DANGERINDEX = 1;
  148.  
  149. const char *castleQueenRook[] =
  150.   {
  151.     "Do you want to castle with Queen's Rook? (Type Y or N):",
  152.     (char *) 0
  153.   };
  154.  
  155. const char *castleKingRook[] =
  156.   {
  157.     "Do you want to castle with King's Rook? (Type Y or N):",
  158.     (char *) 0
  159.   };
  160.  
  161. const char *selectDest[] =
  162.   {
  163.     "Select destination of move with arrow keys, then hit enter:",
  164.     (char *) 0
  165.   };
  166.  
  167. const char *promoteToWhat[] =
  168.   {
  169.     "Do you want your Pawn to be promoted to a Queen, Bishop, "
  170.     "Knight or Rook?  (Type Q, B, K or R):",
  171.     (char *) 0
  172.   };
  173.  
  174. // character key lists
  175.  
  176. const char promoteOptions[] = "qQbBkKrR";
  177. const PIECETYPE promoteType[] = { TYPEQUEEN, TYPEBISHOP, TYPEKNIGHT,
  178.                                   TYPEROOK };
  179.  
  180. const char yesNoAnswer[] = "yYnN";
  181. const int YESINDEX = 0;
  182. const int NOINDEX = 1;
  183.  
  184. // more message text lists
  185.  
  186. const char *thinking[] =
  187.   {
  188.     (char *) 0,
  189.     " Player thinking, please wait...",
  190.     (char *) 0
  191.   };
  192. const int THINKINGCOLORINDEX = 0;
  193.  
  194. const char *doCastleQueenRook[] =
  195.   {
  196.     (char *) 0,
  197.     " Player castles with Queen's Rook.  Press any key to continue:",
  198.     (char *) 0
  199.   };
  200. const char *doCastleKingRook[] =
  201.   {
  202.     (char *) 0,
  203.     " Player castles with King's Rook.  Press any key to continue:",
  204.     (char *) 0
  205.   };
  206. const int CASTLECOLORINDEX = 0;
  207.  
  208. const char *whatMoved[] =
  209.   {
  210.     (char *) 0,
  211.     " Player moves ",
  212.     (char *) 0,
  213.     (char *) 0,
  214.     ".  Press any key to continue:",
  215.     (char *) 0
  216.   };
  217. const int MOVECOLORINDEX = 0;
  218. const int MOVEPIECEINDEX = 2;
  219.  
  220. const char *whatMovedCaptured[] =
  221.   {
  222.     (char *) 0,
  223.     " Player moves ",
  224.     (char *) 0,
  225.     (char *) 0,
  226.     ", capturing ",
  227.     (char *) 0,
  228.     (char *) 0,
  229.     ".  Press any key to continue:",
  230.     (char *) 0
  231.   };
  232. const int CAPTURINGCOLORINDEX = 0;
  233. const int CAPTURINGPIECEINDEX = 2;
  234. const int CAPTUREDPIECEINDEX = 5;
  235.  
  236. const char *doPromotion[] =
  237.   {
  238.     (char *) 0,
  239.     " Player promotes Pawn to ",
  240.     (char *) 0,
  241.     (char *) 0,
  242.     ".  Press any key to continue:",
  243.     (char *) 0
  244.   };
  245. const int PROMOTECOLORINDEX = 0;
  246. const int PROMOTEPIECEINDEX = 2;
  247.  
  248. void CHESSUSERIFACE::outOfMemory(void)
  249.   {
  250.     ChessCharUI.showMessage(noMemory, (char *) 0, (uint *) 0);
  251.  
  252.     return;
  253.   }
  254.  
  255. void CHESSUSERIFACE::init(const BOARD &board)
  256.   {
  257.     int row, col;
  258.     PIECE *p;
  259.  
  260.     ChessCharUI.initScreen();
  261.  
  262.     for (row = 0; row < NUMROWS; row++)
  263.       for (col = 0; col < NUMCOLS; col++)
  264.     {
  265.       p = board.whatPiece(row, col);
  266.       if (p)
  267.         ChessCharUI.showPiece
  268.           (
  269.         POSITION(row, col),
  270.         pieceAbbrev(p->whatColor(), p->whatType())
  271.           );
  272.     }
  273.  
  274.     return;
  275.   }
  276.  
  277. void CHESSUSERIFACE::mated(PIECECOLOR color)
  278.   {
  279.     checkMated[MATEDCOLORINDEX] = colorText(color);
  280.     ChessCharUI.showMessage(checkMated, (char *) 0, (uint *) 0);
  281.  
  282.     return;
  283.   }
  284.  
  285. void CHESSUSERIFACE::staleMated(PIECECOLOR color)
  286.   {
  287.     staleMate[STALEMATEDCOLORINDEX] = colorText(color);
  288.     ChessCharUI.showMessage(staleMate, (char *) 0, (uint *) 0);
  289.  
  290.     return;
  291.   }
  292.  
  293. BOOL CHESSUSERIFACE::userMove(BOARD &board, PIECECOLOR color)
  294.   {
  295.     POSITION start, end;
  296.     PIECE *p;
  297.     uint keyIndex;
  298.     MOVESTATUS moveStatus;
  299.     MOVEUNDODATA dummy;
  300.  
  301.     selectPiece[SELECTCOLORINDEX] = colorText(color);
  302.  
  303.     // loop to get legal move
  304.     for ( ; ; )
  305.       {
  306.     // loop to get piece to move
  307.     for ( ; ; )
  308.       {
  309.         start.row = start.col = 0;
  310.         if (!ChessCharUI.selectPosition(selectPiece, start))
  311.           return(FALSE);
  312.  
  313.         p = board.whatPiece(start);
  314.         if (p)
  315.           if (p->whatColor() == color)
  316.         break;
  317.  
  318.         if (!ChessCharUI.showMessage(illegalSelection,
  319.                      (char *) 0, (uint *) 0))
  320.           return(FALSE);
  321.  
  322.         ChessCharUI.clearSelect(start);
  323.       }
  324.  
  325.     if (board.userCanCastle(QUEENSIDECASTLE, color))
  326.       if ((p->whatType() == TYPEKING) ||
  327.               ((p->whatType() == TYPEROOK) && (start.row == 0)))
  328.         {
  329.           if (!ChessCharUI.showMessage(castleQueenRook,
  330.                        yesNoAnswer, &keyIndex))
  331.         return(FALSE);
  332.           if ((keyIndex / 2) == YESINDEX)
  333.         {
  334.           ChessCharUI.clearSelect(start);
  335.           board.castle(QUEENSIDECASTLE, color, dummy);
  336.           ChessCharUI.clearPiece(POSITION(0, start.col));
  337.           ChessCharUI.showPiece
  338.             (
  339.               POSITION(3, start.col),
  340.               pieceAbbrev(color, TYPEROOK)
  341.             );
  342.           ChessCharUI.clearPiece(POSITION(4, start.col));
  343.           ChessCharUI.showPiece
  344.             (
  345.               POSITION(2, start.col),
  346.               pieceAbbrev(color, TYPEKING)
  347.             );
  348.           return(TRUE);
  349.         }
  350.         }
  351.  
  352.     if (board.userCanCastle(KINGSIDECASTLE, color))
  353.       if ((p->whatType() == TYPEKING) ||
  354.               ((p->whatType() == TYPEROOK) && (start.row == 7)))
  355.         {
  356.           if (!ChessCharUI.showMessage(castleKingRook,
  357.                        yesNoAnswer, &keyIndex))
  358.         return(FALSE);
  359.           if ((keyIndex / 2) == YESINDEX)
  360.         {
  361.           ChessCharUI.clearSelect(start);
  362.           board.castle(KINGSIDECASTLE, color, dummy);
  363.           ChessCharUI.clearPiece(POSITION(7, start.col));
  364.           ChessCharUI.showPiece
  365.             (
  366.               POSITION(5, start.col),
  367.               pieceAbbrev(color, TYPEROOK)
  368.             );
  369.           ChessCharUI.clearPiece(POSITION(4, start.col));
  370.           ChessCharUI.showPiece
  371.             (
  372.               POSITION(6, start.col),
  373.               pieceAbbrev(color, TYPEKING)
  374.             );
  375.           return(TRUE);
  376.         }
  377.         }
  378.  
  379.     end = start;
  380.     if (!ChessCharUI.selectPosition(selectDest, end))
  381.       return(FALSE);
  382.  
  383.     moveStatus = board.doUserMove
  384.                (
  385.              start,
  386.              end
  387.                );
  388.  
  389.     if ((moveStatus.status == MOVEDONE) ||
  390.         (moveStatus.status == MOVEENPASSANT))
  391.       break;
  392.  
  393.     if (moveStatus.status == ILLEGALMOVE)
  394.       {
  395.         if (!ChessCharUI.showMessage(moveIllegal, (char *) 0,
  396.                      (uint *) 0))
  397.           return(FALSE);
  398.       }
  399.     else // king would be taken
  400.       {
  401.         pieceText
  402.           (
  403.         OtherColor(color),
  404.         board.whatPiece(moveStatus.dangerToKing)->whatType(),
  405.         wouldLoseKing + DANGERINDEX
  406.           );
  407.         if (!ChessCharUI.showMessage(wouldLoseKing, (char *) 0,
  408.                      (uint *) 0))
  409.           return(FALSE);
  410.       }
  411.     ChessCharUI.clearSelect(start);
  412.     ChessCharUI.clearSelect(end);
  413.  
  414.       } // end loop to get legal move
  415.  
  416.     ChessCharUI.clearSelect(start);
  417.     ChessCharUI.clearPiece(start);
  418.     ChessCharUI.clearPiece(end);
  419.     if (moveStatus.status == MOVEENPASSANT)
  420.       ChessCharUI.clearPiece(POSITION(end.row, start.col));
  421.     ChessCharUI.showPiece
  422.       (
  423.     end,
  424.     pieceAbbrev(color, p->whatType())
  425.       );
  426.  
  427.     if (board.canPromote(end))
  428.       {
  429.     if (!ChessCharUI.showMessage(promoteToWhat, promoteOptions,
  430.                      &keyIndex))
  431.       return(FALSE);
  432.     keyIndex /= 2;
  433.     board.promote(end, promoteType[keyIndex]);
  434.     ChessCharUI.clearPiece(end);
  435.     ChessCharUI.showPiece
  436.       (
  437.         end,
  438.         pieceAbbrev(color, promoteType[keyIndex])
  439.       );
  440.       }
  441.     ChessCharUI.clearSelect(end);
  442.  
  443.     return(TRUE);
  444.   }
  445.  
  446. void CHESSUSERIFACE::thinkingMessage(PIECECOLOR color)
  447.   {
  448.     thinking[THINKINGCOLORINDEX] = colorText(color);
  449.  
  450.     ChessCharUI.showMessage(thinking);
  451.  
  452.     return;
  453.   }
  454.  
  455. void CHESSUSERIFACE::clearMessage(void)
  456.   {
  457.     ChessCharUI.clearMessage();
  458.  
  459.     return;
  460.   }
  461.  
  462. BOOL CHESSUSERIFACE::computerMove
  463.   (
  464.     BOARD &board,
  465.     PIECECOLOR color,
  466.     PIECEMOVE &moveInfo
  467.   )
  468.   {
  469.     int backCol = color == WHITE ? 0 : 7;
  470.     MOVEUNDODATA undoData;
  471.  
  472.     switch (moveInfo.type)
  473.       {
  474.       case KINGSIDECASTLE:
  475.     board.castle(KINGSIDECASTLE, color, undoData);
  476.     ChessCharUI.clearPiece(POSITION(7, backCol));
  477.     ChessCharUI.clearPiece(POSITION(4, backCol));
  478.     ChessCharUI.showPiece
  479.       (
  480.         POSITION(5, backCol),
  481.         pieceAbbrev(color, TYPEROOK)
  482.       );
  483.     ChessCharUI.showPiece
  484.       (
  485.         POSITION(6, backCol),
  486.         pieceAbbrev(color, TYPEKING)
  487.       );
  488.     ChessCharUI.setSelect(POSITION(5, backCol));
  489.     ChessCharUI.setSelect(POSITION(6, backCol));
  490.     doCastleKingRook[CASTLECOLORINDEX] = colorText(color);
  491.     if (!ChessCharUI.showMessage(doCastleKingRook,
  492.                      (char *) 0, (uint *) 0))
  493.       return(FALSE);
  494.     ChessCharUI.clearSelect(POSITION(5, backCol));
  495.     ChessCharUI.clearSelect(POSITION(6, backCol));
  496.     return(TRUE);
  497.     
  498.       case QUEENSIDECASTLE:
  499.     board.castle(QUEENSIDECASTLE, color, undoData);
  500.     ChessCharUI.clearPiece(POSITION(0, backCol));
  501.     ChessCharUI.clearPiece(POSITION(4, backCol));
  502.     ChessCharUI.showPiece
  503.       (
  504.         POSITION(3, backCol),
  505.         pieceAbbrev(color, TYPEROOK)
  506.       );
  507.     ChessCharUI.showPiece
  508.       (
  509.         POSITION(2, backCol),
  510.         pieceAbbrev(color, TYPEKING)
  511.       );
  512.     ChessCharUI.setSelect(POSITION(3, backCol));
  513.     ChessCharUI.setSelect(POSITION(2, backCol));
  514.     doCastleQueenRook[CASTLECOLORINDEX] = colorText(color);
  515.     if (!ChessCharUI.showMessage(doCastleQueenRook,
  516.                      (char *) 0, (uint *) 0))
  517.       return(FALSE);
  518.     ChessCharUI.clearSelect(POSITION(3, backCol));
  519.     ChessCharUI.clearSelect(POSITION(2, backCol));
  520.     return(TRUE);
  521.     
  522.       case NORMALMOVE:
  523.     board.doMove(moveInfo.start, moveInfo.end, undoData);
  524.     ChessCharUI.clearPiece(moveInfo.start);
  525.     ChessCharUI.clearPiece(moveInfo.end);
  526.     if (undoData.enPassantEffect == ENPASSANTCAPTURE)
  527.       ChessCharUI.clearPiece(POSITION(moveInfo.end.row,
  528.                       moveInfo.start.col));
  529.     ChessCharUI.showPiece
  530.       (
  531.         moveInfo.end,
  532.         pieceAbbrev(color,
  533.                 board.whatPiece(moveInfo.end)->whatType())
  534.       );
  535.     ChessCharUI.setSelect(moveInfo.start);
  536.     ChessCharUI.setSelect(moveInfo.end);
  537.  
  538.     if (undoData.capturedPiece)
  539.       {
  540.         whatMovedCaptured[CAPTURINGCOLORINDEX] = colorText(color);
  541.         pieceText
  542.           (
  543.         color,
  544.         board.whatPiece(moveInfo.end)->whatType(),
  545.         whatMovedCaptured + CAPTURINGPIECEINDEX
  546.           );
  547.         pieceText
  548.           (
  549.         OtherColor(color),
  550.         undoData.capturedPiece->whatType(),
  551.         whatMovedCaptured + CAPTUREDPIECEINDEX
  552.           );
  553.  
  554.         delete undoData.capturedPiece;
  555.  
  556.         if (!ChessCharUI.showMessage(whatMovedCaptured,
  557.                      (char *) 0, (uint *) 0))
  558.           return(FALSE);
  559.       }
  560.     else
  561.       {
  562.         whatMoved[MOVECOLORINDEX] = colorText(color);
  563.         pieceText
  564.           (
  565.         color,
  566.         board.whatPiece(moveInfo.end)->whatType(),
  567.         whatMoved + MOVEPIECEINDEX
  568.           );
  569.         if (!ChessCharUI.showMessage(whatMoved,
  570.                      (char *) 0, (uint *) 0))
  571.           return(FALSE);
  572.       }
  573.  
  574.     if (moveInfo.promoteType != TYPENOPIECE)
  575.       {
  576.         board.promote(moveInfo.end, moveInfo.promoteType);
  577.         ChessCharUI.clearPiece(moveInfo.end);
  578.         ChessCharUI.showPiece
  579.           (
  580.         moveInfo.end,
  581.         pieceAbbrev(color, moveInfo.promoteType)
  582.           );
  583.         doPromotion[PROMOTECOLORINDEX] = colorText(color);
  584.         pieceText
  585.           (
  586.         color,
  587.         moveInfo.promoteType,
  588.         doPromotion + PROMOTEPIECEINDEX
  589.           );
  590.         if (!ChessCharUI.showMessage(doPromotion, (char *) 0,
  591.                      (uint *) 0))
  592.           return(FALSE);
  593.       }
  594.     ChessCharUI.clearSelect(moveInfo.start);
  595.     ChessCharUI.clearSelect(moveInfo.end);
  596.  
  597.     return(TRUE);
  598.  
  599.       } // end of switch
  600.  
  601.     return(FALSE);
  602.  
  603.   } // end of function
  604.